using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using CodePlex.SpaceBlock;

namespace CodePlex.SpaceBlock.UI
{
    public class MetadataDescriptor : ICustomTypeDescriptor
    {
        private readonly Metadata _metadata;
        private readonly MetadataTypeConverter _converter;

        public MetadataDescriptor(Metadata metadata)
        {
            _metadata = metadata;
            _converter = new MetadataTypeConverter(this);
        }

        public Metadata Metadata
        {
            get
            {
                return _metadata;
            }
        }

        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return _metadata;
        }

        public AttributeCollection GetAttributes()
        {
            AttributeCollection rt = new AttributeCollection();
            return rt;
        }

        public object GetEditor(Type editorBaseType)
        {
            return null;
        }

        public string GetClassName()
        {
            return _metadata.GetType().FullName;
        }

        public TypeConverter GetConverter()
        {
            return _converter;
        }

        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            return null;
        }

        public PropertyDescriptor GetDefaultProperty()
        {
            return null;
        }

        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return null;
        }

        public string GetComponentName()
        {
            throw new NotImplementedException();
        }

        public EventDescriptor GetDefaultEvent()
        {
            throw new NotImplementedException();
        }

        public EventDescriptorCollection GetEvents()
        {
            throw new NotImplementedException();
        }

        public PropertyDescriptorCollection GetProperties()
        {
            throw new NotImplementedException();
        }







        private class MetadataTypeConverter : TypeConverter
        {

            private readonly MetadataDescriptor _parent;

            public MetadataTypeConverter(MetadataDescriptor parent)
            {
                _parent = parent;
            }

            public override bool GetPropertiesSupported(ITypeDescriptorContext context)
            {
                return true;
            }

            public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
            {
                List<PropertyDescriptor> props = new List<PropertyDescriptor>();

                foreach (string key in _parent.Metadata.Keys)
                {
                    MetadataPropertyDescriptor mpd = new MetadataPropertyDescriptor(
                        this,
                        key,
                        _parent.Metadata.GetCategory(key),
                        _parent.Metadata.GetDescription(key)
                        );
                    
                    props.Add(mpd);

                }
                return new PropertyDescriptorCollection(props.ToArray());
            }

          
       

            private class MetadataPropertyDescriptor : PropertyDescriptor
            {
                private readonly MetadataTypeConverter _parent;

                public MetadataPropertyDescriptor(MetadataTypeConverter parent, string name, string category, string description)
                    : base(name, new Attribute[] { 
                        new CategoryAttribute(category),
                        new DescriptionAttribute(description)})
                {
                    _parent = parent;
                }

                public override object GetValue(object component)
                {
                    Metadata metadata = component as Metadata;
                    return metadata[this.Name];
                }

                public override bool IsReadOnly
                {
                    get 
                    {
                        return _parent._parent.Metadata.GetReadOnly(this.Name);
                    }
                }

                public override Type PropertyType
                {
                    get { return typeof(string); }
                }

                public override bool ShouldSerializeValue(object component)
                {
                    return false;
                }

                public override void SetValue(object component, object value)
                {
                    Metadata metadata = component as Metadata;
                    metadata[this.Name] = value as string;
                }

                public override bool CanResetValue(object component)
                {
                    throw new NotImplementedException();
                }

                public override Type ComponentType
                {
                    get
                    {
                        throw new NotImplementedException();
                    }
                }
              
                public override void ResetValue(object component)
                {
                    throw new NotImplementedException();
                }


            }
         
        }
    }
}
